package cn.fintecher.pangolin.service.manage.request;

import cn.fintecher.pangolin.common.enums.CaseDataStatus;
import cn.fintecher.pangolin.common.enums.PublicCaseFlag;
import cn.fintecher.pangolin.common.enums.StrategyType;
import cn.fintecher.pangolin.common.utils.ZWDateUtil;
import cn.fintecher.pangolin.entity.mysql.QCaseInfo;
import com.querydsl.core.BooleanBuilder;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.apache.commons.lang.StringUtils;
import org.json.JSONArray;
import org.json.JSONObject;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * @Auther: xiaqun
 * @Description: 案件预览请求
 * @Date: 15:04 2019/9/24
 */

@Data
public class CaseStrategyPreviewRequest {
    @ApiModelProperty(value = "策略类型")
    private StrategyType strategyType;

    @ApiModelProperty(value = "委托方集合")
    private List<String> principalIds;

    @ApiModelProperty(value = "委案城市集合")
    private String cities;

    @ApiModelProperty(value = "公式JSON")
    private String formulaJson;

    public BooleanBuilder getBuilder() throws Exception {
        BooleanBuilder builder = new BooleanBuilder();
        QCaseInfo qCaseInfo = QCaseInfo.caseInfo;
        builder.and(qCaseInfo.strategyId.isNull());
        if (this.strategyType.equals(StrategyType.DEPARTMENT)) {
            builder.and(qCaseInfo.department.isNotNull()).and(qCaseInfo.currentCollector.isNull())
                    .and(qCaseInfo.caseDataStatus.ne(CaseDataStatus.PAUSE).or(qCaseInfo.caseDataStatus.isNull()))
                    .and(qCaseInfo.publicCaseFlag.eq(PublicCaseFlag.NO_PUBLIC_CASE).or(qCaseInfo.publicCaseFlag.isNull()));
        } else if (this.strategyType.equals(StrategyType.COLLECTING)) {
            builder.and(qCaseInfo.department.isNull()).and(qCaseInfo.currentCollector.isNotNull())
                    .and(qCaseInfo.caseDataStatus.in(CaseDataStatus.IN_POOL,CaseDataStatus.SETTLT,CaseDataStatus.REDUCE))
                    .and(qCaseInfo.publicCaseFlag.eq(PublicCaseFlag.NO_PUBLIC_CASE).or(qCaseInfo.publicCaseFlag.isNull()));
        } else if (this.strategyType.equals(StrategyType.PUBLIC)) {
            builder.and(qCaseInfo.publicCaseFlag.eq(PublicCaseFlag.PUBLIC_CASE));
        } else if (this.strategyType.equals(StrategyType.STOPPING)) {
            builder.and(qCaseInfo.caseDataStatus.eq(CaseDataStatus.PAUSE));
        }
        if (Objects.nonNull(this.principalIds) && !this.principalIds.isEmpty()) {
            builder.and(qCaseInfo.principalId.in(this.principalIds));
        }
        if (StringUtils.isNotBlank(this.cities)) {
            List<String> city = Arrays.asList(this.cities.split(","));
            List<String> list = new ArrayList<>();
            city.forEach(e -> {
                if (StringUtils.isNotBlank(e)) {
                    list.add(e);
                }
            });
            if (!list.isEmpty()) {
                builder.and(qCaseInfo.city.in(list));
            }
        }
        if (StringUtils.isNotBlank(this.formulaJson)) {
            analysisFormula(this.formulaJson, builder);
        }
        return builder;
    }

    /**
     * 处理json
     */
    private void analysisFormula(String json, BooleanBuilder builder) throws Exception {
        JSONArray jsonArray = new JSONArray(json);
        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject jsonObj = jsonArray.getJSONObject(i);
            if (jsonObj.getBoolean("leaf")) {
                processSituation(builder, jsonObj.get("variable").toString(), jsonObj.get("symbol").toString(), jsonObj.get("value").toString());
            } else {
                BooleanBuilder builder1 = new BooleanBuilder();
                analysisFormula(jsonObj.getJSONArray("children").toString(), builder1);
                builder.and(builder1);
            }
        }
    }

    /**
     * 处理条件
     */
    private void processSituation(BooleanBuilder builder, String variable, String symbol, String value) throws ParseException {
        QCaseInfo qCaseInfo = QCaseInfo.caseInfo;
        switch (symbol) {
            case ">":
                switch (variable) {
                    case "overdueAmtTotal":
                        builder.and(qCaseInfo.overdueAmtTotal.gt(Double.parseDouble(value)));
                        break;
                    case "leftAmt":
                        builder.and(qCaseInfo.leftAmt.gt(Double.parseDouble(value)));
                        break;
                    case "overduePeriods":
                        builder.and(qCaseInfo.overduePeriods.gt(Integer.parseInt(value)));
                        break;
                    case "overdueDays":
                        builder.and(qCaseInfo.overdueDays.gt(Integer.parseInt(value)));
                        break;
                    case "delegationDate":
                        builder.and(qCaseInfo.delegationDate.gt(Objects.requireNonNull(ZWDateUtil.getUtilDate(value, "yyyy-MM-dd"))));
                        break;
                    case "endCaseDate":
                        builder.and(qCaseInfo.endCaseDate.gt(Objects.requireNonNull(ZWDateUtil.getUtilDate(value, "yyyy-MM-dd"))));
                        break;
                    default:
                        break;
                }
                break;
            case ">=":
                switch (variable) {
                    case "overdueAmtTotal":
                        builder.and(qCaseInfo.overdueAmtTotal.goe(Double.parseDouble(value)));
                        break;
                    case "leftAmt":
                        builder.and(qCaseInfo.leftAmt.goe(Double.parseDouble(value)));
                        break;
                    case "overduePeriods":
                        builder.and(qCaseInfo.overduePeriods.goe(Integer.parseInt(value)));
                        break;
                    case "overdueDays":
                        builder.and(qCaseInfo.overdueDays.goe(Integer.parseInt(value)));
                        break;
                    case "delegationDate":
                        builder.and(qCaseInfo.delegationDate.goe(ZWDateUtil.getFormatDate(value)));
                        break;
                    case "endCaseDate":
                        builder.and(qCaseInfo.endCaseDate.goe(ZWDateUtil.getFormatDate(value)));
                        break;
                    default:
                        break;
                }
                break;
            case "<":
                switch (variable) {
                    case "overdueAmtTotal":
                        builder.and(qCaseInfo.overdueAmtTotal.lt(Double.parseDouble(value)));
                        break;
                    case "leftAmt":
                        builder.and(qCaseInfo.leftAmt.lt(Double.parseDouble(value)));
                        break;
                    case "overduePeriods":
                        builder.and(qCaseInfo.overduePeriods.lt(Integer.parseInt(value)));
                        break;
                    case "overdueDays":
                        builder.and(qCaseInfo.overdueDays.lt(Integer.parseInt(value)));
                        break;
                    case "delegationDate":
                        builder.and(qCaseInfo.delegationDate.lt(ZWDateUtil.getFormatDate(value)));
                        break;
                    case "endCaseDate":
                        builder.and(qCaseInfo.endCaseDate.lt(ZWDateUtil.getFormatDate(value)));
                        break;
                    default:
                        break;
                }
                break;
            case "<=":
                switch (variable) {
                    case "overdueAmtTotal":
                        builder.and(qCaseInfo.overdueAmtTotal.loe(Double.parseDouble(value)));
                        break;
                    case "leftAmt":
                        builder.and(qCaseInfo.leftAmt.loe(Double.parseDouble(value)));
                        break;
                    case "overduePeriods":
                        builder.and(qCaseInfo.overduePeriods.loe(Integer.parseInt(value)));
                        break;
                    case "overdueDays":
                        builder.and(qCaseInfo.overdueDays.loe(Integer.parseInt(value)));
                        break;
                    case "delegationDate":
                        builder.and(qCaseInfo.delegationDate.loe(ZWDateUtil.getFormatDate(value)));
                        break;
                    case "endCaseDate":
                        builder.and(qCaseInfo.endCaseDate.loe(ZWDateUtil.getFormatDate(value)));
                        break;
                    default:
                        break;
                }
                break;
            case "==":
                switch (variable) {
                    case "overdueAmtTotal":
                        builder.and(qCaseInfo.overdueAmtTotal.eq(Double.parseDouble(value)));
                        break;
                    case "leftAmt":
                        builder.and(qCaseInfo.leftAmt.eq(Double.parseDouble(value)));
                        break;
                    case "overduePeriods":
                        builder.and(qCaseInfo.overduePeriods.eq(Integer.parseInt(value)));
                        break;
                    case "overdueDays":
                        builder.and(qCaseInfo.overdueDays.eq(Integer.parseInt(value)));
                        break;
                    case "delegationDate":
                        builder.and(qCaseInfo.delegationDate.eq(ZWDateUtil.getFormatDate(value)));
                        break;
                    case "endCaseDate":
                        builder.and(qCaseInfo.endCaseDate.eq(ZWDateUtil.getFormatDate(value)));
                        break;
                    default:
                        break;
                }
                break;
            default:
                break;
        }
    }
}
